{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 对几个经过 one-hot 处理过的字段进行logistic回归计算\n",
    "['source_system_tab', 'source_screen_name', 'source_type', 'city', 'bd', 'gender', 'registered_via', 'song_length', 'language', 'reg_interval_days']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 首先 import 必要的模块\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import pickle as pk\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "import math\n",
    "import scipy.io as sio\n",
    "import scipy.sparse as ss\n",
    "import timeit\n",
    "%matplotlib inline\n",
    "\n",
    "from sklearn.model_selection import GridSearchCV"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_path = '../Data/'  # 文件路径\n",
    "model_path = '../model/' # 模型路径"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 读取数据 onehot 数据\n",
    "with open(model_path+'data_all_train_onehot.pkl', 'rb') as fr:\n",
    "    X_train = pk.load(fr)\n",
    "fr.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 读取 训练数据集 标签数据\n",
    "with open(model_path+'target_list.pkl', 'rb') as fr:\n",
    "    Y_train = pk.load(fr)\n",
    "fr.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(7377418, 109)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>source_system_tab_discover</th>\n",
       "      <th>source_system_tab_explore</th>\n",
       "      <th>source_system_tab_listen with</th>\n",
       "      <th>source_system_tab_my library</th>\n",
       "      <th>source_system_tab_notification</th>\n",
       "      <th>source_system_tab_radio</th>\n",
       "      <th>source_system_tab_search</th>\n",
       "      <th>source_system_tab_settings</th>\n",
       "      <th>source_system_tab_tab_NaN</th>\n",
       "      <th>source_screen_name_Album more</th>\n",
       "      <th>...</th>\n",
       "      <th>reg_interval_days_1</th>\n",
       "      <th>reg_interval_days_2</th>\n",
       "      <th>reg_interval_days_3</th>\n",
       "      <th>reg_interval_days_4</th>\n",
       "      <th>reg_interval_days_5</th>\n",
       "      <th>reg_interval_days_6</th>\n",
       "      <th>reg_interval_days_7</th>\n",
       "      <th>reg_interval_days_8</th>\n",
       "      <th>reg_interval_days_9</th>\n",
       "      <th>reg_interval_days_10</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>201969</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1932462</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>183559</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>149511</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>74867</th>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 109 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "         source_system_tab_discover  source_system_tab_explore  \\\n",
       "201969                            0                          1   \n",
       "1932462                           0                          0   \n",
       "183559                            0                          0   \n",
       "149511                            0                          0   \n",
       "74867                             0                          1   \n",
       "\n",
       "         source_system_tab_listen with  source_system_tab_my library  \\\n",
       "201969                               0                             0   \n",
       "1932462                              0                             1   \n",
       "183559                               0                             1   \n",
       "149511                               0                             1   \n",
       "74867                                0                             0   \n",
       "\n",
       "         source_system_tab_notification  source_system_tab_radio  \\\n",
       "201969                                0                        0   \n",
       "1932462                               0                        0   \n",
       "183559                                0                        0   \n",
       "149511                                0                        0   \n",
       "74867                                 0                        0   \n",
       "\n",
       "         source_system_tab_search  source_system_tab_settings  \\\n",
       "201969                          0                           0   \n",
       "1932462                         0                           0   \n",
       "183559                          0                           0   \n",
       "149511                          0                           0   \n",
       "74867                           0                           0   \n",
       "\n",
       "         source_system_tab_tab_NaN  source_screen_name_Album more  ...  \\\n",
       "201969                           0                              0  ...   \n",
       "1932462                          0                              0  ...   \n",
       "183559                           0                              0  ...   \n",
       "149511                           0                              0  ...   \n",
       "74867                            0                              0  ...   \n",
       "\n",
       "         reg_interval_days_1  reg_interval_days_2  reg_interval_days_3  \\\n",
       "201969                     0                    0                    0   \n",
       "1932462                    0                    0                    0   \n",
       "183559                     0                    0                    0   \n",
       "149511                     0                    0                    0   \n",
       "74867                      0                    0                    0   \n",
       "\n",
       "         reg_interval_days_4  reg_interval_days_5  reg_interval_days_6  \\\n",
       "201969                     0                    0                    0   \n",
       "1932462                    0                    0                    0   \n",
       "183559                     0                    0                    0   \n",
       "149511                     0                    0                    0   \n",
       "74867                      0                    0                    0   \n",
       "\n",
       "         reg_interval_days_7  reg_interval_days_8  reg_interval_days_9  \\\n",
       "201969                     1                    0                    0   \n",
       "1932462                    0                    1                    0   \n",
       "183559                     0                    1                    0   \n",
       "149511                     0                    1                    0   \n",
       "74867                      1                    0                    0   \n",
       "\n",
       "         reg_interval_days_10  \n",
       "201969                      0  \n",
       "1932462                     0  \n",
       "183559                      0  \n",
       "149511                      0  \n",
       "74867                       0  \n",
       "\n",
       "[5 rows x 109 columns]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "201969     1\n",
       "1932462    1\n",
       "183559     1\n",
       "149511     1\n",
       "74867      1\n",
       "Name: target, dtype: int64"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Y_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "#保存特征名字以备后用（可视化）\n",
    "feat_names = X_train.columns "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "#sklearn的学习器大多之一稀疏数据输入，模型训练会快很多\n",
    "#查看一个学习器是否支持稀疏数据，可以看fit函数是否支持: X: {array-like, sparse matrix}.\n",
    "#可自行用timeit比较稠密数据和稀疏数据的训练时间\n",
    "from scipy.sparse import csr_matrix\n",
    "X_train = csr_matrix(X_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "lr = LogisticRegression()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/letv/hubo/anaconda3/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:432: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n",
      "  FutureWarning)\n",
      "/letv/hubo/anaconda3/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:432: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n",
      "  FutureWarning)\n",
      "/letv/hubo/anaconda3/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:432: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n",
      "  FutureWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "logloss of each fold is:  [0.63485782 0.64936283 0.68487527]\n",
      "cv logloss is: 0.6563653081206504\n"
     ]
    }
   ],
   "source": [
    "# 交叉验证用于评估模型性能和进行参数调优（模型选择）\n",
    "#分类任务中交叉验证缺省是采用StratifiedKFold\n",
    "#数据集比较大，采用3折交叉验证\n",
    "from sklearn.model_selection import cross_val_score\n",
    "loss = cross_val_score(lr, X_train, Y_train, cv=3, scoring='neg_log_loss')  # 负loglss损失函数\n",
    "# %timeit loss_sparse = cross_val_score(lr, X_train_sparse, y_train, cv=3, scoring='neg_log_loss')\n",
    "print ('logloss of each fold is: ',-loss)   \n",
    "print ('cv logloss is:', -loss.mean())  # logloss 平均值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 正则化的 Logistic Regression 及参数调优"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "logistic 回归的需要调整超参数有：Cs（正则系数，一般在log域（取log后的值）均匀设置候选参数）和正则函数penalty（L2/L1） \n",
    "目标函数为：J =  C* sum(logloss(f(xi), yi)) + penalty \n",
    "\n",
    "在sklearn框架下，不同学习器的参数调整步骤相同：\n",
    "设置参数搜索范围\n",
    "生成 GridSearchCV 的实例（参数）\n",
    "调用GridSearchCV的fit方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/letv/hubo/anaconda3/lib/python3.7/site-packages/sklearn/linear_model/logistic.py:432: FutureWarning: Default solver will be changed to 'lbfgs' in 0.22. Specify a solver to silence this warning.\n",
      "  FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "GridSearchCV(cv=3, error_score='raise-deprecating',\n",
       "             estimator=LogisticRegression(C=1.0, class_weight=None, dual=False,\n",
       "                                          fit_intercept=True,\n",
       "                                          intercept_scaling=1, l1_ratio=None,\n",
       "                                          max_iter=100, multi_class='warn',\n",
       "                                          n_jobs=None, penalty='l2',\n",
       "                                          random_state=None, solver='warn',\n",
       "                                          tol=0.0001, verbose=0,\n",
       "                                          warm_start=False),\n",
       "             iid='warn', n_jobs=-1,\n",
       "             param_grid={'C': [0.001, 0.01, 0.1, 1, 10, 100, 1000],\n",
       "                         'penalty': ['l1', 'l2']},\n",
       "             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,\n",
       "             scoring='neg_log_loss', verbose=0)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.model_selection import GridSearchCV\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "\n",
    "#需要调优的参数\n",
    "# 请尝试将L1正则和L2正则分开，并配合合适的优化求解算法（slover）\n",
    "#tuned_parameters = {'penalty':['l1','l2'],\n",
    "#                   'C': [0.001, 0.01, 0.1, 1, 10, 100, 1000]\n",
    "#                   }\n",
    "penaltys = ['l1','l2']\n",
    "Cs = [0.001, 0.01, 0.1, 1, 10, 100, 1000]\n",
    "tuned_parameters = dict(penalty = penaltys, C = Cs)\n",
    "\n",
    "lr_penalty= LogisticRegression(solver='sag')\n",
    "grid= GridSearchCV(lr_penalty,tuned_parameters,scoring='neg_log_loss',n_jobs=-1,cv=3)\n",
    "grid.fit(X_train,Y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.6562430576089365\n",
      "{'C': 0.001, 'penalty': 'l2'}\n"
     ]
    }
   ],
   "source": [
    "# examine the best model\n",
    "print(-grid.best_score_)  # 最好的分数\n",
    "print(grid.best_params_)  # 最好的分数对应的参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'mean_fit_time': array([ 883.33777086,  113.0664471 , 4506.36842163,  197.21981533,\n",
       "        3743.9419109 ,  258.35149717,  415.96040479,  248.28181012,\n",
       "         432.50065915,  298.62775699,  479.82549659,  302.68667388,\n",
       "         342.91373301,  230.62373114]),\n",
       " 'std_fit_time': array([ 161.28098798,   17.30566107, 1141.0537874 ,   20.16272616,\n",
       "        1416.5959889 ,   35.78590299,  107.11767433,   14.20240194,\n",
       "          18.36748717,   75.01372943,   74.05189552,   79.39356416,\n",
       "          38.48935473,   48.77758817]),\n",
       " 'mean_score_time': array([0.91046063, 1.5191404 , 0.71114691, 1.58910569, 0.68370247,\n",
       "        1.55741612, 1.65179451, 1.65298462, 1.60040808, 1.6321106 ,\n",
       "        0.99130432, 1.55722642, 1.13414129, 1.07948494]),\n",
       " 'std_score_time': array([0.21635159, 0.15144099, 0.06767868, 0.06332878, 0.10308476,\n",
       "        0.08499877, 0.07301436, 0.05884443, 0.07343912, 0.11959663,\n",
       "        0.11920035, 0.08439056, 0.19841823, 0.17734283]),\n",
       " 'param_C': masked_array(data=[0.001, 0.001, 0.01, 0.01, 0.1, 0.1, 1, 1, 10, 10, 100,\n",
       "                    100, 1000, 1000],\n",
       "              mask=[False, False, False, False, False, False, False, False,\n",
       "                    False, False, False, False, False, False],\n",
       "        fill_value='?',\n",
       "             dtype=object),\n",
       " 'param_penalty': masked_array(data=['l1', 'l2', 'l1', 'l2', 'l1', 'l2', 'l1', 'l2', 'l1',\n",
       "                    'l2', 'l1', 'l2', 'l1', 'l2'],\n",
       "              mask=[False, False, False, False, False, False, False, False,\n",
       "                    False, False, False, False, False, False],\n",
       "        fill_value='?',\n",
       "             dtype=object),\n",
       " 'params': [{'C': 0.001, 'penalty': 'l1'},\n",
       "  {'C': 0.001, 'penalty': 'l2'},\n",
       "  {'C': 0.01, 'penalty': 'l1'},\n",
       "  {'C': 0.01, 'penalty': 'l2'},\n",
       "  {'C': 0.1, 'penalty': 'l1'},\n",
       "  {'C': 0.1, 'penalty': 'l2'},\n",
       "  {'C': 1, 'penalty': 'l1'},\n",
       "  {'C': 1, 'penalty': 'l2'},\n",
       "  {'C': 10, 'penalty': 'l1'},\n",
       "  {'C': 10, 'penalty': 'l2'},\n",
       "  {'C': 100, 'penalty': 'l1'},\n",
       "  {'C': 100, 'penalty': 'l2'},\n",
       "  {'C': 1000, 'penalty': 'l1'},\n",
       "  {'C': 1000, 'penalty': 'l2'}],\n",
       " 'split0_test_score': array([-0.63553936, -0.63504694, -0.63492421, -0.63487407, -0.63486107,\n",
       "        -0.63485822, -0.6348577 , -0.63485782, -0.63485663, -0.63485709,\n",
       "        -0.6348578 , -0.63485716, -0.63485724, -0.63485705]),\n",
       " 'split1_test_score': array([-0.6495586 , -0.64934122, -0.64933716, -0.64934801, -0.64935783,\n",
       "        -0.6493601 , -0.64935964, -0.64936283, -0.64936015, -0.64936283,\n",
       "        -0.64936239, -0.64936274, -0.64935982, -0.64936306]),\n",
       " 'split2_test_score': array([-0.68406454, -0.68434103, -0.6847135 , -0.68479975, -0.68484996,\n",
       "        -0.68486844, -0.68486804, -0.68487527, -0.68486398, -0.68487663,\n",
       "        -0.68486622, -0.68487715, -0.68486628, -0.68487704]),\n",
       " 'mean_test_score': array([-0.65638749, -0.65624306, -0.65632495, -0.6563406 , -0.65635628,\n",
       "        -0.65636224, -0.65636179, -0.6563653 , -0.65636025, -0.65636551,\n",
       "        -0.65636213, -0.65636568, -0.6563611 , -0.65636571]),\n",
       " 'std_test_score': array([0.02039033, 0.02070754, 0.02091834, 0.02097325, 0.0209993 ,\n",
       "        0.02100838, 0.02100843, 0.0210113 , 0.0210069 , 0.02101217,\n",
       "        0.02100727, 0.02101239, 0.02100777, 0.02101234]),\n",
       " 'rank_test_score': array([14,  1,  2,  3,  4,  9,  7, 10,  5, 11,  8, 12,  6, 13],\n",
       "       dtype=int32)}"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grid.cv_results_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYgAAAEGCAYAAAB/+QKOAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAWoElEQVR4nO3df7RdZZ3f8fcnIRgUKDQJFghOgCZdAyqhRJSJg2BRMmrBn4AjOtNpRaussbqkYm2xoK6xyzVdrumkFUQrTIHAgGAGMwRnRHGokQQMkoSJhqjlGpQYYSAFmoR8+8fZgZObnXByc0/OzeX9Wuuuu/ezn73P98lN7if7d6oKSZKGmzDoAiRJY5MBIUlqZUBIkloZEJKkVgaEJKnVfoMuYLRMnTq1ZsyYMegyJGmfcs899/y6qqa1LRs3ATFjxgyWLVs26DIkaZ+S5Oc7W+YhJklSKwNCktTKgJAktRo35yAkqdvmzZsZGhri6aefHnQpY8LkyZOZPn06kyZN6nkdA0LSuDQ0NMRBBx3EjBkzSDLocgaqqtiwYQNDQ0McffTRPa/nISZJ49LTTz/NlClTXvDhAJCEKVOm7PbelAEhadwyHJ4zkj8LA0KSGude/n3Ovfz7gy5jzDAgNCaNp3+ojmXseXD9Rh5cv7Hvn3PggQcCsHz5ck455RSOP/54XvnKV3L99dfv0PfDH/4ws2fP5rjjjuOAAw5g9uzZzJ49mxtvvHGXnzF8LPfeey+33XbbqNTvSepxZNs/3Os/cMqAK5HU7cUvfjFXX301M2fOZN26dZx00kmceeaZHHLIIc/2mT9/PgA/+9nPeMtb3sLy5ctH9Fn33nsvK1asYN68eXtct3sQjJ//FUkam2bNmsXMmTMBOOKIIzjssMNYv359z+v/5Cc/4cwzz+Skk07i1FNP5cc//jEACxYs4PdOPZm3nHYKp59+Ok899RSXXXYZ11xzTU97H8/HPQhJ496lf7WSVesef3b+6c3PADB50sTt+q16uNOnl/8wHnfEwXz6Xx6/27XcfffdbNq0iWOPPbbndS644AKuvPJKjj32WO666y4uvPBCbr/9di699FL+4sZvMvWww5gyaQsHHHAAl1xyCStWrOCLX/zibtc2nAEhSXvJww8/zHvf+16uuuoqJkzo7QDOY489xpIlS3jHO97xbNuWLVsAmDt3Lh+/8AJ+76y38sE/+P1Rr9eAkDTuDf+f/raTusdOO3C79n6ex3v88cd585vfzGc/+1le85rX9LxeVTF16tTWcxJf/vKXuem2O7jjW7dxwgkn8KMf/Wg0S/YchCT126ZNm3jb297G+973Pt71rnft1rqHHnoohx9+ODfffDMAW7du5b777gNg7dq1nDjnZD568X/i0EMP5Re/+AUHHXQQTzzxxKjUbUBIUp/dcMMN3HnnnXzta1979vLV3blKacGCBXzpS1/ihBNO4Pjjj+fWW28F4KMf/Shvet2redPrXs0ZZ5zBy1/+cl7/+tdz3333ceKJJ3qSWpLGqo0bO4eyzj//fM4///ye1pkxYwYrVqzYru2YY45h8eLFO/RduHDhDofLpk2bNmovTzMgJKnhPUTb8xCTJKmVASFp3KqqQZcwZozkz8KAkDQuTZ48mQ0bNhgSPPc+iMmTJ+/Wep6DkDQuTZ8+naGhodZHWqx/4v8BsOnXL9rbZY26Xsey7Y1yu8OAkDQuTZo0aadvT/vPz94QN3tvltQX/RyLh5gkSa0MCElSKwNCktTKgJAktTIgJEmtDAhJUisDQpLUyoCQJLUyICRJrQwISVIrA0KS1MqAkCS1MiAkSa0MCElSKwNCktTKgJAktTIgJEmt+hoQSeYlWZ1kTZKLd9LnnCSrkqxMcm3TdnqS5V1fTyd5az9rlSRtr2+vHE0yEZgPvAEYApYmWVhVq7r6zAQ+CcytqkeTHAZQVXcAs5s+/xhYA9zer1olSTvq5x7EycCaqlpbVZuABcDZw/q8H5hfVY8CVNUjLdt5J/DXVfVkH2uVJA3Tz4A4Enioa36oaes2C5iV5K4kS5LMa9nOecB1bR+Q5IIky5IsW79+/agULUnq6GdApKWths3vB8wETgPeDVyZ5JBnN5AcDrwCWNz2AVV1RVXNqao506ZNG5WiJUkd/QyIIeCorvnpwLqWPt+oqs1V9VNgNZ3A2OYc4Oaq2tzHOiVJLfoZEEuBmUmOTrI/nUNFC4f1uQU4HSDJVDqHnNZ2LX83Ozm8JEnqr74FRFVtAS6kc3joAeCGqlqZ5LIkZzXdFgMbkqwC7gAuqqoNAElm0NkD+W6/apQk7VzfLnMFqKpFwKJhbZd0TRfwseZr+Lo/Y8eT2pKkvcQ7qSVJrQwISVIrA0KS1MqAkCS1MiAkSa0MCElSKwNCktTKgJAktTIgJEmtDAhJUisDQpLUyoCQJLUyICRJrQwISVIrA0KS1MqAkCS1MiAkSa0MCElSKwNCktTKgJAktTIgJEmtDAhJUisDQpLUyoCQJLUyICRJrQwISVIrA0KS1MqAkCS1MiAkSa0MCElSKwNCktTKgJAktTIgJEmtDAhJUisDQpLUyoCQJLUyICRJrQwISVKrvgZEknlJVidZk+TinfQ5J8mqJCuTXNvV/rIktyd5oFk+o5+1SpK2t1+/NpxkIjAfeAMwBCxNsrCqVnX1mQl8EphbVY8mOaxrE1cDn6uqbyU5ENjar1olSTvq5x7EycCaqlpbVZuABcDZw/q8H5hfVY8CVNUjAEmOA/arqm817Rur6sk+1ipJGqafAXEk8FDX/FDT1m0WMCvJXUmWJJnX1f5Ykq8n+WGSLzR7JNtJckGSZUmWrV+/vi+DkKQXqn4GRFraatj8fsBM4DTg3cCVSQ5p2n8X+DjwKuAY4A932FjVFVU1p6rmTJs2bfQqlyTtfkAkmZDk4B66DgFHdc1PB9a19PlGVW2uqp8Cq+kExhDww+bw1BbgFuCf726tkqSR6ykgklyb5OAkLwFWAauTXPQ8qy0FZiY5Osn+wHnAwmF9bgFObz5jKp1DS2ubdQ9Nsm234PXN50qS9pJe9yCOq6rHgbcCi4CXAe/d1QrN//wvBBYDDwA3VNXKJJclOavpthjYkGQVcAdwUVVtqKpn6Bxe+tsk99M5XPXl3RybJGkP9HqZ66Qkk+gExJ9X1eYkw88n7KCqFtEJlO62S7qmC/hY8zV83W8Br+yxPknSKOt1D+Jy4GfAS4A7k/wW8Hi/ipIkDV5PexBV9WfAn3U1/TzJ6f0pSZI0FvR6kvojzUnqJPlKknvpnDiWJI1TvR5i+qPmJPUbgWnAvwI+37eqJEkD12tAbLvp7U3A/6yq+2i/EU6SNE70GhD3JLmdTkAsTnIQPjxPksa1Xi9z/dfAbGBtVT2ZZAqdw0ySpHGq16uYtiaZDvx+EoDvVtVf9bUySdJA9XoV0+eBj9B53MUq4I+T/Ek/C5MkDVavh5jeBMyuqq0ASa4CfkjnZT+SpHFod94odwjwm2b6H/WhloF4ZmuxaUvnfPu6x55iaxVVnfatVWwtmu/F1q1d09vat7ZPP1NF7WSdZ7Z2PmOH6aZPNe3bpjv9aGobNt213Z9veBIoPnPrKqp5EEo1T1ivYQ9Gqaahnp1/rv9z09svY9i2dvYZbdvsXvDc8p3VAGse2UgBF157785/eMM877NfRmml2s2VfvKrJwD40DX37P6HjTE/bsbyb//Xvj2W8TIO6Ixl8qQdXpczKnoNiD8BfpjkDjqXt57KONl7ePTJTfzwoccA+J3Pf3vA1eyeBCYkTExIYPMznaC7fmnnPU3PXoec7b7RnEciO2vvWrZt6Y59t83velsM79/jev930xYAVj28e090Gcm118NrHe3PeWpz5+fyk19t3O3PGWuebsby4Pp9eyzjZRzQGcuEEfwd7kWvJ6mvS/IdOi/vCfCJqvplXyrayw580X7MmPJiAnzgdccyYUKYkDAhMHFCSDPdaXtuurOsfXpCOr90JjbrtC6b0LXdCe2fsUP7hO37DP/Fdu7l3wfg+g+cMoA/ydHlWMam8TKW8TIOeG4s/bDLgEgy/CU9Q833I5IcUVW97/+PUZMnTeSlB08G4LyTXzbgaiRp7Hi+PYg/3cWywucxSdK4tcuAqCqf2CpJL1A9nYNI8vaW5n8A7q+qR0a3JEnSWLA7j9o4hc5rQQFOA5YAs5JcVlV/0YfaJEkD1GtAbAV+u6p+BZDkpcD/AF4N3AkYEJI0zvT6NNcZ28Kh8Qgwq6p+A2we/bIkSYPW6x7E95LcCvxlM/9OOu+mfgnwWF8qkyQNVK8B8WHg7cBr6dwodxVwU3WeleCVTpI0DvV6J3Ul+TtgE537H+6uGv50H0nSeNLr477PAe6mc2jpHOAHSd7Zz8IkSYPV6yGmTwGv2nbPQ5JpwN8AN/arMEnSYPV6FdOEYTfEbdiNdSVJ+6Be9yBuS7IYuK6ZPxdY1J+SJEljQa8nqS9K8g5gLp2rmK6oqpv7WpkkaaB6fqNcVd0E3NTHWiRJY8jzvQ/iCdpfyhg6V78e3JeqJEkD93yP+z5obxUiSRpbvBJJktTKgJAktTIgJEmtDAhJUisDQpLUyoCQJLUyICRJrfoaEEnmJVmdZE2Si3fS55wkq5KsTHJtV/szSZY3Xwv7WackaUc9P2pjdyWZCMwH3gAMAUuTLKyqVV19ZgKfBOZW1aNJDuvaxFNVNbtf9UmSdq2fexAnA2uqam1VbQIWAGcP6/N+YH5VPQow7JHikqQB6mdAHAk81DU/1LR1mwXMSnJXkiVJ5nUtm5xkWdP+1rYPSHJB02fZ+vXrR7d6SXqB69shJjoP9Btu+IP/9gNmAqcB04HvJXl5VT0GvKyq1iU5Bvh2kvur6sHtNlZ1BXAFwJw5c3xHtiSNon7uQQwBR3XNTwfWtfT5RlVtrqqfAqvpBAZVta75vhb4DnBiH2uVJA3Tz4BYCsxMcnSS/YHzgOFXI90CnA6QZCqdQ05rkxya5EVd7XOBVUiS9pq+HWKqqi1JLgQWAxOBr1bVyiSXAcuqamGz7I1JVgHPABdV1YYkvwNcnmQrnRD7fPfVT5Kk/uvnOQiqahHD3l1dVZd0TRfwsearu8//Bl7Rz9okSbvmndSSpFYGhCSplQEhSWplQEiSWhkQkqRWBoQkqZUBIUlqZUBIkloZEJKkVgaEJKmVASFJamVASJJaGRCSpFYGhCSplQEhSWplQEiSWhkQkqRWBoQkqZUBIUlqZUBIkloZEJKkVgaEJKmVASFJamVASJJaGRCSpFYGhCSplQEhSWplQEiSWhkQkqRWBoQkqZUBIUlqZUBIkloZEJKkVgaEJKmVASFJamVASJJaGRCSpFYGhCSpVV8DIsm8JKuTrEly8U76nJNkVZKVSa4dtuzgJL9I8uf9rFOStKP9+rXhJBOB+cAbgCFgaZKFVbWqq89M4JPA3Kp6NMlhwzbzGeC7/apRkrRz/dyDOBlYU1Vrq2oTsAA4e1if9wPzq+pRgKp6ZNuCJCcBLwVu72ONkqSd6GdAHAk81DU/1LR1mwXMSnJXkiVJ5gEkmQD8KXDRrj4gyQVJliVZtn79+lEsXZLUz4BIS1sNm98PmAmcBrwbuDLJIcCHgEVV9RC7UFVXVNWcqpozbdq0UShZkrRN385B0NljOKprfjqwrqXPkqraDPw0yWo6gXEK8LtJPgQcCOyfZGNVtZ7oliSNvn7uQSwFZiY5Osn+wHnAwmF9bgFOB0gylc4hp7VV9Z6qellVzQA+DlxtOEjS3tW3gKiqLcCFwGLgAeCGqlqZ5LIkZzXdFgMbkqwC7gAuqqoN/apJktS7fh5ioqoWAYuGtV3SNV3Ax5qvnW3ja8DX+lOhJGlnvJNaktTKgJAktTIgJEmtDAhJUisDQpLUyoCQJLUyICRJrQwISVIrA0KS1MqAkCS1MiAkSa0MCElSKwNCktTKgJAktTIgJEmt+vo+iH3F9R84ZdAlSNKYk847e/Z9c+bMqWXLlg26DEnapyS5p6rmtC3zEJMkqZUBIUlqZUBIkloZEJKkVgaEJKmVASFJamVASJJaGRCSpFYGhCSp1bi5kzrJeuDne7CJqcCvR6mcQRov4wDHMlaNl7GMl3HAno3lt6pqWtuCcRMQeyrJsp3dbr4vGS/jAMcyVo2XsYyXcUD/xuIhJklSKwNCktTKgHjOFYMuYJSMl3GAYxmrxstYxss4oE9j8RyEJKmVexCSpFYGhCSplQHRSPKZJD9KsjzJ7UmOGHRNI5XkC0n+vhnPzUkOGXRNI5XkXUlWJtmaZJ+7JDHJvCSrk6xJcvGg69kTSb6a5JEkKwZdy55IclSSO5I80Pzd+sigaxqpJJOT3J3kvmYsl47q9j0H0ZHk4Kp6vJn+Y+C4qvrggMsakSRvBL5dVVuS/BeAqvrEgMsakSS/DWwFLgc+XlX7zHtlk0wEfgy8ARgClgLvrqpVAy1shJKcCmwErq6qlw+6npFKcjhweFXdm+Qg4B7grfvizyVJgJdU1cYkk4C/Az5SVUtGY/vuQTS2hUPjJcA+m5xVdXtVbWlmlwDTB1nPnqiqB6pq9aDrGKGTgTVVtbaqNgELgLMHXNOIVdWdwG8GXceeqqqHq+reZvoJ4AHgyMFWNTLVsbGZndR8jdrvLgOiS5LPJXkIeA9wyaDrGSV/BPz1oIt4gToSeKhrfoh99BfReJVkBnAi8IPBVjJySSYmWQ48AnyrqkZtLC+ogEjyN0lWtHydDVBVn6qqo4BrgAsHW+2uPd9Ymj6fArbQGc+Y1ctY9lFpadtn90zHmyQHAjcB/27YEYR9SlU9U1Wz6RwpODnJqB3+22+0NrQvqKozeux6LfBN4NN9LGePPN9YkvwB8BbgX9QYP9G0Gz+Xfc0QcFTX/HRg3YBqUZfmeP1NwDVV9fVB1zMaquqxJN8B5gGjciHBC2oPYleSzOyaPQv4+0HVsqeSzAM+AZxVVU8Oup4XsKXAzCRHJ9kfOA9YOOCaXvCaE7tfAR6oqv866Hr2RJJp265STHIAcAaj+LvLq5gaSW4C/hmdK2Z+Dnywqn4x2KpGJska4EXAhqZpyT58RdbbgP8GTAMeA5ZX1ZmDrap3Sd4EfBGYCHy1qj434JJGLMl1wGl0Hi39K+DTVfWVgRY1AkleC3wPuJ/Ov3eA/1BViwZX1cgkeSVwFZ2/XxOAG6rqslHbvgEhSWrjISZJUisDQpLUyoCQJLUyICRJrQwISVIrA0LaDUk2Pn+vXa5/Y5JjmukDk1ye5MHmSZx3Jnl1kv2b6RfUjawaewwIaS9JcjwwsarWNk1X0nn43cyqOh74Q2Bq82C/vwXOHUihUsOAkEYgHV9onhl1f5Jzm/YJSf57s0dwa5JFSd7ZrPYe4BtNv2OBVwP/saq2AjRPff1m0/eWpr80MO7CSiPzdmA2cAKdO4uXJrkTmAvMAF4BHEbnUdJfbdaZC1zXTB9P567wZ3ay/RXAq/pSudQj9yCkkXktcF3zJM1fAd+l8wv9tcBfVtXWqvolcEfXOocD63vZeBMcm5oX2kgDYUBII9P2KO9dtQM8BUxuplcCJyTZ1b/BFwFPj6A2aVQYENLI3Amc27ysZRpwKnA3nVc+vqM5F/FSOg+32+YB4J8CVNWDwDLg0ubpoiSZue0dGEmmAOuravPeGpA0nAEhjczNwI+A+4BvA/++OaR0E533QKyg8x7tHwD/0KzzTbYPjH8D/BNgTZL7gS/z3PsiTgf2uaeLanzxaa7SKEtyYPMS+Sl09irmVtUvm+f139HM7+zk9LZtfB345D78Pm6NA17FJI2+W5uXuOwPfKbZs6CqnkryaTrvpf4/O1u5ebnQLYaDBs09CElSK89BSJJaGRCSpFYGhCSplQEhSWplQEiSWv1/az0yvif1M3oAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# plot CV误差曲线\n",
    "test_means = grid.cv_results_[ 'mean_test_score' ]\n",
    "test_stds = grid.cv_results_[ 'std_test_score' ]\n",
    "\n",
    "# plot results\n",
    "n_Cs = len(Cs)\n",
    "number_penaltys = len(penaltys)\n",
    "test_scores = np.array(test_means).reshape(n_Cs,number_penaltys)\n",
    "# train_scores = np.array(train_means).reshape(n_Cs,number_penaltys)\n",
    "test_stds = np.array(test_stds).reshape(n_Cs,number_penaltys)\n",
    "# train_stds = np.array(train_stds).reshape(n_Cs,number_penaltys)\n",
    "\n",
    "x_axis = np.log10(Cs)\n",
    "for i, value in enumerate(penaltys):\n",
    "#     pyplot.plot(log(Cs), test_scores[i], label= 'penalty:'   + str(value))\n",
    "    plt.errorbar(x_axis, -test_scores[:,i], yerr=test_stds[:,i] ,label = penaltys[i] +' Test')\n",
    "    #plt.errorbar(x_axis, -train_scores[:,i], yerr=train_stds[:,i] ,label = penaltys[i] +' Train')\n",
    "    \n",
    "plt.legend()\n",
    "plt.xlabel( 'log(C)' )                                                                                                      \n",
    "plt.ylabel( 'logloss' )\n",
    "plt.savefig('LogisticGridSearchCV_C.png' )\n",
    "\n",
    "plt.show()\n",
    "\n",
    "\n",
    "plt.errorbar(x_axis, -test_scores[:,1], yerr=test_stds[:,1] ,label = penaltys[1] +' Test')\n",
    "plt.legend()\n",
    "plt.xlabel( 'log(C)' )                                                                                                      \n",
    "plt.ylabel( 'logloss' )\n",
    "plt.savefig('LogisticGridSearchCV_C.png' )\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "上图给出了L1正则和L2正则下、不同正则参数C对应的模型在训练集上测试集上的logloss。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "pk.dump(grid.best_estimator_, open(model_path+'Music_logistic_onehot.pkl','wb'))  # 保存模型"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用 LogisticRegressionCV 查找最优的超参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LogisticRegressionCV(Cs=[0.001, 0.01, 0.1, 1, 10, 100, 1000], class_weight=None,\n",
       "                     cv=3, dual=False, fit_intercept=True,\n",
       "                     intercept_scaling=1.0, l1_ratios=None, max_iter=100,\n",
       "                     multi_class='ovr', n_jobs=None, penalty='l2',\n",
       "                     random_state=None, refit=True, scoring='neg_log_loss',\n",
       "                     solver='sag', tol=0.0001, verbose=0)"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegressionCV\n",
    "\n",
    "Cs = [1e-3, 1e-2, 1e-1, 1, 10, 100, 1000]\n",
    "#nCs = 9  #Cs values are chosen in a logarithmic scale between 1e-4 and 1e4.\n",
    "\n",
    "# 大量样本（6W+）、高维度（93），L1正则 --> 可选用saga优化求解器(0.19版本新功能)\n",
    "# LogisticRegressionCV比GridSearchCV快\n",
    "lrcv_L1 = LogisticRegressionCV(Cs=Cs, cv = 3, scoring='neg_log_loss', penalty='l2', solver='sag', multi_class='ovr')\n",
    "lrcv_L1.fit(X_train, Y_train)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{1: array([[-0.63503622, -0.63487334, -0.63485791, -0.63485696, -0.63485821,\n",
       "         -0.6348577 , -0.63485761],\n",
       "        [-0.64933534, -0.64934731, -0.6493605 , -0.64936323, -0.64936332,\n",
       "         -0.64936349, -0.64936358],\n",
       "        [-0.68437321, -0.6848056 , -0.68486978, -0.68487881, -0.68487831,\n",
       "         -0.68487817, -0.68487856]])}"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lrcv_L1.scores_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "# scores_：dict with classes as the keys, and the values as the grid of scores obtained during cross-validating each fold,\n",
    "# Each dict value has shape (n_folds, len(Cs))\n",
    "Cs = [1e-3, 1e-2, 1e-1, 1, 10, 100, 1000]\n",
    "n_Cs = len(Cs)\n",
    "n_classes = 1\n",
    "scores =  np.zeros((n_Cs))\n",
    "\n",
    "scores = -np.mean(lrcv_L1.scores_[1],axis = 0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.65624826, 0.65634208, 0.65636273, 0.65636633, 0.65636661,\n",
       "       0.65636645, 0.65636659])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(np.log10(Cs), scores) \n",
    "#plt(np.log10(reg.Cs)*np.ones(3), [0.28, 0.29, 0.30])\n",
    "plt.xlabel('log(C)')\n",
    "plt.ylabel('logloss')\n",
    "plt.show()\n",
    "\n",
    "#print ('C is:',lr_cv.C_)  #对多类分类问题，每个类别的分类器有一个C"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C is: [0.001]\n"
     ]
    }
   ],
   "source": [
    "print ('C is:',lrcv_L1.C_)  #对多类分类问题，每个类别的分类器有一个C"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
